home *** CD-ROM | disk | FTP | other *** search
- APM
- apmInit(init, scale_factor, base)
- long init;
- int scale_factor;
- short base;
- {}
- This routine initializes a new APM value. The 'init' parameter is a long
- integer that represents its initial value, the 'scale_factor' variable
- indicates how this initial value should be scaled, and 'base' is the base of
- the initial value. Note that the APM value returned by this routine is
- normally a reclaimed APM value that has been previously disposed of via
- apmDispose(); only if there are no previous values to be reclaimed will this
- routine allocate a fresh APM value (see also the apmGarbageCollect()
- routine).
-
- Bases can be 2 - 36, 10000, or 0, where 0 defaults to base 10000.
-
- If the call fails, it will return (APM)NULL and 'apm_errno' will contain a
- meaningful result. Otherwise, a new APM value will be initialized.
-
- For example, assume that we want to initialize two APM values in base 10000,
- the first to 1.23456 and the second to 1 E20 ("one times 10 to the 20th
- power"):
-
- APM apm_1 = apmInit(123456L, -5, 0);
- APM apm_2 = apmInit(1L, 20, 0);
-
- As a convenience, the following macro is defined in apm.h:
-
- #define apmNew(BASE) apmInit(0L, 0, (BASE))
-
- int
- apmDispose(apm)
- APM apm;
- {}
- This routine disposes of a APM value 'apm' by returning it to the list of
- unused APM values (see also the apmGarbageCollect() routine). It returns
- an appropriate status which is also put into 'apm_errno'.
-
- int
- apmGarbageCollect()
- {}
- When APM values are disposed of, they remain allocated. Subsequent calls to
- apmInit() may then return a previously allocated but disposed APM value.
- This is done for speed considerations, but after a while there may be lots of
- these unused APM values lying around. This routine reclaims the space taken
- up by these unused APM values (it frees them). It returns an appropriate
- status which is also put into 'apm_errno'.
-
- int
- apmAdd(result, apm1, apm2)
- APM result;
- APM apm1;
- APM apm2;
- {}
- This routine adds 'apm1' and 'apm2', putting the sum into 'result', whose
- previous value is destroyed. Note that all three parameters must have been
- previously initialized via apmInit().
-
- The 'result' parameter cannot be one of the other APM parameters.
-
- The return code and the 'apm_error' variable reflect the status of this
- function.
-
- int
- apmSubtract(result, apm1, apm2)
- APM result;
- APM apm1;
- APM apm2;
- {}
- This routine subtracts 'apm2' from 'apm1', putting the difference into
- 'result', whose previous value is destroyed. Note that all three parameters
- must have been previously initialized via apmInit().
-
- The 'result' parameter cannot be one of the other APM parameters.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmMultiply(result, apm1, apm2)
- APM result;
- APM apm1;
- APM apm2;
- {}
- This routine multiplies 'apm1' and 'apm2', putting the product into 'result',
- whose previous value is destroyed. Note that all three parameters must have
- been previously initialized via apmInit().
-
- The 'result' parameter cannot be one of the other APM parameters.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmDivide(quotient, radix_places, remainder, apm1, apm2)
- APM quotient;
- int radix_places;
- APM remainder;
- APM apm1;
- APM apm2;
- {}
- This routine divides 'apm1' by 'apm2', producing the 'quotient' and
- 'remainder' variables. Unlike the other three basic operations,
- division cannot be counted on to produce non-repeating decimals, so
- the 'radix_places' variable exists to tell this routine how many
- digits to the right of the radix point are to be calculated before
- stopping. If the 'remainder' variable is set to (APM)NULL, no
- remainder is calculated ... this saves quite a bit of computation time
- and hence is recommended whenever possible.
-
- All APM values must have been previously initialized via apmInit() (except,
- of course the 'remainder' value if it is to be set to NULL).
-
- Division by zero creates a zero result and a warning.
-
- The 'quotient' and 'remainder' variables can't be one of the other APM
- parameters.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmCompare(apm1, apm2)
- APM apm1;
- APM apm2;
- {}
- This routine compares 'apm1' and 'apm2', returning -1 if 'apm1' is less than
- 'apm2', 1 if 'apm1' is greater than 'apm2', and 0 if they are equal.
-
- It is not an error if 'apm1' and 'apm2' are identical, and in this case the
- return value is 0.
-
- The 'apm_errno' variable contains the error code. You must check this value:
- if it is set to an error indication, the comparison failed and the return
- value is therefore meaningless.
-
- int
- apmCompareLong(apm, longval, scale_factor, base)
- APM apm;
- long longval;
- int scale_factor;
- short base;
- {}
- This routine works just like apmCompare(), but it compares the 'apm' value to
- 'longval', scaled by 'scale_factor' in 'base'. The 'apm_errno' variable
- contains the error code.
-
- int
- apmSign(apm)
- APM apm;
- {}
- This routine returns the sign of the 'apm' value: -1 for negative, 1 for
- positive. The 'apm_errno' variable contains the error code. You must check
- 'apm_errno': if it's non-zero, the function return value is meaningless.
-
- int
- apmAbsoluteValue(result, apm)
- APM result;
- APM apm;
- {}
- This routine puts the absolute value of 'apm' into 'result', whose previous
- value is destroyed. Note that the two parameters must have been previously
- initialized via apmInit().
-
- The 'result' parameter cannot be the other APM parameter.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmNegate(result, apm)
- APM result;
- APM num;
- {}
- This routine puts the additive inverse of 'apm' into 'result', whose previous
- value is destroyed. Note that the two parameters must have been previously
- initialized via apmInit().
-
- The 'result' parameter cannot be the other APM parameter.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmReciprocal(result, radix_places, apm)
- APM result;
- int radix_places;
- APM num;
- {}
- This routine puts the multiplicative inverse of 'apm' into 'result', whose
- previous value is destroyed. Note that the two APM parameters must have been
- previously initialized via apmInit(). Since taking the reciprocal involves
- doing a division, the 'radix_places' parameter is needed here for the same
- reason it's needed in the apmDivide() routine.
-
- Taking the reciprocal of zero yields zero with a warning status.
-
- The 'result' parameter cannot be the other APM parameter.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmScale(result, apm, scale_factor)
- APM result;
- APM apm;
- int scale_factor;
- {}
- This routine assigns to 'result' the value of 'apm' with its radix point
- shifted by 'scale_factor' (positive 'scale_factor' means shift left). The
- 'scale_factor' represents how many places the radix is shifted in the base of
- 'apm' unless 'apm' is in base 10000 ... in this special case, 'scale_factor'
- is treated as if the base were 10.
-
- This is a very quick and accurate way to multiply or divide by a power of 10
- (or the number's base).
-
- The 'result' parameter cannot be the other APM parameter.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmValidate(apm)
- APM apm;
- {}
- This routine sets 'apm_errno' and its return status to some non-zero value if
- 'apm' is not a valid APM value.
-
- int
- apmAssign(result, apm)
- APM result;
- APM num;
- {}
- This routine assigns the value of 'apm' to 'result', whose previous value is
- destroyed. Note that the two parameters must have been previously
- initialized via apmInit().
-
- It is not considered an error if 'result' and 'apm' are identical; this case
- is a virtual no-op.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmAssignLong(result, long_value, scale_factor, base)
- APM result;
- long long_value;
- int scale_factor;
- short base;
- {}
- This routine assigns a long int to 'result'. Its second through fourth
- parameters correspond exactly to the parameters of apmInit(). The only
- difference between the two routines is that this one requires that its result
- be previously initialized. The 'long_value' parameter is a long that
- represents the value to assign to 'result', the 'scale_factor' variable
- indicates how this value should be scaled, and 'base' is the base of the
- value.
-
- Bases can be 2 - 36, 10000, or 0, where 0 defaults to base 10000.
-
- For example, assume that we want to assign values to two previously
- initialized APM entities, apm_1 and apm_2. The base will be base 10000, the
- first value will be set to 1.23456 and the second will be set to 1 E20 ("one
- times 10 to the 20th power"):
-
- int ercode;
-
- ercode = apmAssignLong(apm_1, 123456L, -5, 0);
- ...
-
- ercode = apmAssignLong(apm_2, 1L, 20, 0);
- ...
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmAssignString(apm, string, base)
- APM apm;
- char *string;
- short base;
- {}
- This routine takes a character string containing the ASCII representation of
- a numeric value and converts it into a APM value in the base specified. The
- 'apm' parameter must have been previously initialized, 'string' must be
- non-NULL and valid in the specified base, and 'base' must be a valid base.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- apmConvert(string, length, decimals, round, leftjustify, apm)
- char *string;
- int length;
- int decimals;
- int round;
- int leftjustify;
- APM apm;
- {}
- This routine converts a APM value 'apm' into its ASCII representation
- 'string'. The 'length' parameter is the maximum size of the string (including
- the trailing null), the 'decimals' parameter is the number of decimal places
- to display, the 'round' parameter is a true-false value which determines
- whether rounding is to take place (0 = false = no rounding), the
- 'leftjustify' parameter is a true-false value which determines whether the
- result is to be left justified (0 = false = right justify; non-zero = true =
- left justify), and the 'apm' paramter is the APM value to be converted.
-
- The 'string' parameter must point to an area that can hold at least 'length'
- bytes.
-
- If the 'decimals' parameter is < 0, the string will contain the number of
- decimal places that are inherent in the APM value passed in.
-
- The return code and the 'apm_errno' variable reflect the status of this
- function.
-
- int
- (*apmErrorFunc(newfunc))()
- int (*newfunc)();
- {}
- This routine registers an error handler for errors and warnings. Before any
- of the other APM routines return to the caller, an optional error handler
- specified in 'newfunc' can be called to intercept the result of the
- operation. With a registered error handler, the caller can dispense with the
- repetitious code for checking 'apm_errno' or the function return status after
- each call to a APM routine.
-
- If no error handler is registered or if 'newfunc' is set to NULL, no action
- will be taken on errors and warnings except to set the 'apm_errno' variable.
- If there is an error handler, it is called as follows when there is an error
- or a warning:
-
- retcode = (*newfunc)(ercode, message, file, line, function)
-
- where ...
-
- int retcode; /* returned by 'newfunc': should be 'ercode' */
- int ercode; /* error code */
- char *message; /* a short string describing the error */
- char *file; /* the file in which the error occurred */
- int line; /* the line on which the error occurred */
- char *function; /* the name of the function in error */
-
- Note that your error handler should normally return 'ercode' unless it does a
- longjmp, calls exit(), or in some other way interrupts the normal processing
- flow. The value returned from your error handler is the value that the apm
- routine in error will return to its caller.
-
- The error handler is called after 'apm_errno' is set.
-
- This routine returns a pointer to the previously registered error handler or
- NULL if one isn't registered.
-
- int
- apmCalc(result, operand, ..., NULL)
- APM result;
- APM operand, ...;
- {}
- This routine performs a series of calculations in an RPN ("Reverse
- Polish Notation") fashion, returning the final result in the 'result'
- variable. It takes a variable number of arguments and hence the
- rightmost argument must be a NULL.
-
- Each 'operand' is either a APM value or a special constant indicating
- the operation that is to be performed (see below). This routine makes
- use of a stack (16 levels deep) similar to that in many pocket
- calculators. It also is able to access a set of 16 auxiliary
- registers (numbered 0 through 15) for holding intermediate values.
-
- The stack gets reinitialized at the start of this routine, so values
- that have been left on the stack from a previous call will disappear.
- However, the auxiliary registers are static and values remain in these
- registers for the duration of your program. They may also be
- retrieved outside of this routine (see the apmGetRegister() and
- apmSetRegister() routines, below).
-
- An operand that is an APM value is automatically pushed onto the stack
- simply by naming it in the function call. If the stack is full when a
- value is being pushed onto it, the bottommost value drops off the
- stack and the push succeeds; this is similar to how many pocket
- calculators work. Also, if the stack is empty, a pop will succeed,
- yielding a zero value and keeping the stack empty. The topmost value
- on the stack is automatically popped into the 'result' parameter after
- all the operations have been performed.
-
- An operand that is one of the following special values will cause
- an operation to be performed. These operations are described in the
- following list. Note that the values "V", "V1", and "V2" are used
- in the following list to stand for temporary values:
-
- APM_ABS pop V, push absolute value of V
- APM_NEG pop V, push -V
- APM_CLEAR empty the stack
- APM_DUP pop V, push V, push V
- APM_SWAP pop V1, pop V2, push V1, push V2
- APM_SCALE(N) pop V, push V scaled by N [ as in apmScale() ]
- APM_PUSH(N) V = value in register N, push V
- APM_POP(N) pop V, store it in register N
- APM_ADD pop V1, pop V2, push (V2 + V1)
- APM_SUB pop V1, pop V2, push (V2 - V1)
- APM_MUL pop V1, pop V2, push (V2 * V1)
- APM_DIV(N) pop V1, pop V2, push (V2 / V1) with N radix places
- [ as in apmDivide() ], remainder goes into register 0
- APM_RECIP(N) pop V, push 1/V with N radix places
- [ as in apmReciprocal() ]
-
- Since register 0 is used to hold the remainder in a division, it is
- recommended that this register not be used to hold other values.
-
- As an example, assume that APM values "foo", "bar", and "baz" have
- been initialized via apmInit() and that "foo" and "bar" are to be used
- to calculate "baz" as follows (assume that divisions stop after 16
- decimal places have been calcluated):
-
- baz = 1 / ((((foo * bar) + foo) / bar) - foo)
-
- The function call will be:
-
- bcdCalc(baz, foo, APM_DUP, APM_POP(1), bar, APM_DUP, APM_POP(2),
- APM_MUL, APM_PUSH(1), APM_ADD, APM_PUSH(2), APM_DIV(16),
- APM_PUSH(1), APM_SUB, APM_RECIP(16), NULL);
-
- Note that the value of "foo" is stored in register 1 and the value of
- "bar" is stored in register 2. After this call, these registers will
- still contain those values.
-
- int
- apmGetRegister(regvalue, regnumber)
- APM regvalue;
- int regnumber;
- {}
- The value in auxiliary register number 'regnumber' is assigned to APM
- value 'regvalue'. The 'regnumber' parameter must be between 0 and 15,
- inclusive. The 'regvalue' parameter must have been previously
- initialized via apmInit().
-
- int
- apmSetRegister(regvalue, regnumber, newvalue)
- APM regvalue;
- int regnumber;
- APM newvalue;
- {}
- The value in auxiliary register number 'regnumber' is assigned to APM
- value 'regvalue', and then the APM value 'newvalue' is stored in that
- same register. The 'regnumber' parameter must be between 0 and 15,
- inclusive. The 'regvalue' and 'newvalue' parameters must have been
- previously initialized via apmInit().
-